#include "MapWindow.h"
#include <QDebug>

using namespace qmapcontrol;

MapWindow::MapWindow(QWidget *parent)
    :QDialog(parent), isUsePin(false)
{
    /// Create map control
    mapControl = new MapControl(QSize(500, 500));
    mapControl->showScale(true);

    /// Create mapadapter, for mainlayer and overlay
    mapAdapter = new OSMMapAdapter();

    /// Create a layer with the mapadapter and type MapLayer
    mainLayer = new MapLayer("OpenStreetMap-Layer", mapAdapter);

    /// Add Layer to the MapControl
    mapControl->addLayer(mainLayer);

    /// Sets the view to the interesting area
    mapControl->setView(QPointF(30.52333, 50.45));
    mapControl->setZoom(15);

    /// Set cashe folder
    /// \todo Get this folder from settings
    ImageManager::instance()->setCacheDir(QDir("/home/green/Diploma/MapCache"));

    /// Init gui elements and show map control
    initCommonUi();
    addZoomButtons();

    /// Prepare pin cursor
    pinCursor = new QCursor(QPixmap(":/Resources/images/pin.png"));

    /// Connect mouse click event on map
    connect(mapControl, SIGNAL(mouseEventCoordinate(const QMouseEvent*,QPointF)),
            this, SLOT(processMouseEventCoordinate(const QMouseEvent*,QPointF)));

    /// Connect click events of the layer to this object
    connect(mainLayer, SIGNAL(geometryClicked(Geometry*, QPoint)),
                      this, SLOT(geometryClicked(Geometry*, QPoint)));

}

MapWindow::~MapWindow()
{
    delete pinCursor;
    removeAllGepmetry();
}

void MapWindow::initCommonUi()
{
    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(mapControl);
    setLayout(layout);
    setModal(false);
}

void MapWindow::addZoomButtons()
{
    /// Create buttons as controls for zoom
    QPushButton* zoomin = new QPushButton("+");
    QPushButton* zoomout = new QPushButton("-");
    zoomin->setMaximumWidth(50);
    zoomout->setMaximumWidth(50);

    connect(zoomin, SIGNAL(clicked(bool)),
            mapControl, SLOT(zoomIn()));
    connect(zoomout, SIGNAL(clicked(bool)),
            mapControl, SLOT(zoomOut()));

    /// Add zoom buttons to the layout of the MapControl
    QVBoxLayout* innerlayout = new QVBoxLayout;
    innerlayout->addWidget(zoomin);
    innerlayout->addWidget(zoomout);
    mapControl->setLayout(innerlayout);
}

void MapWindow::resizeEvent(QResizeEvent *event)
{
    mapControl->resize(event->size());
}

void MapWindow::setUsePin(bool usePin)
{
    isUsePin = usePin;
    if(usePin)
        mapControl->setCursor(Qt::CrossCursor);
    else
        mapControl->setCursor(Qt::ArrowCursor);
}

void MapWindow::processMouseEventCoordinate(const QMouseEvent *evnt, const QPointF coordinate)
{
    if(evnt->type() == QEvent::MouseButtonRelease && isUsePin)
        emit pinDroped(coordinate);
}

void MapWindow::geometryClicked(Geometry *geom, QPoint coord_px)
{
    CirclePointMapPtr point;
    foreach(point, circlePointList)
        if(point.get() == geom)
        {
            emit circlePointClicked(point);
            break;
        }
}

void MapWindow::addCirclePoint(CirclePointMapPtr circlePoint)
{
    if(!circlePoint)
        return;

    circlePointList.push_back(circlePoint);
    mainLayer->addGeometry(circlePoint.get());
    mapControl->updateRequestNew();
}

void MapWindow::removeCirclePoint(CirclePointMapPtr circlePoint)
{
    if(!circlePoint)
        return;

    bool isOk;
    isOk = circlePointList.removeOne(circlePoint);
    if(isOk)
    {
        mainLayer->removeGeometry(circlePoint.get());
        mapControl->updateRequestNew();
    }
}

void MapWindow::addLineString(LineStringMapPtr lineString,
                              CirclePointMapPtr fromPoint,
                              CirclePointMapPtr toPoint)
{
    if(!lineString)
        return;

    bool isFromPointInList = circlePointList.contains(fromPoint);
    bool isToPointInList = circlePointList.contains(toPoint);

    /// Remove points from geopmetry
    if(fromPoint && isFromPointInList)
        mainLayer->removeGeometry(fromPoint.get());
    if(toPoint && isToPointInList)
        mainLayer->removeGeometry(toPoint.get());

    lineStringList.push_back(lineString);
    mainLayer->addGeometry(lineString.get());

    /// Back points to geometry
    if(fromPoint && isFromPointInList)
        mainLayer->addGeometry(fromPoint.get());
    if(toPoint && isToPointInList)
        mainLayer->addGeometry(toPoint.get());

    /// Update whlo;e map
    mapControl->updateRequestNew();
}

void MapWindow::removeLineString(LineStringMapPtr lineString)
{
    if(!lineString)
        return;

    bool isOk;
    isOk = lineStringList.removeOne(lineString);
    if(isOk)
    {
        mainLayer->removeGeometry(lineString.get());
        mapControl->updateRequestNew();
    }
}

void MapWindow::removeAllGepmetry()
{
    CirclePointMapPtr cp;
    foreach(cp, circlePointList)
        mainLayer->removeGeometry(cp.get());

    LineStringMapPtr ls;
    foreach(ls, lineStringList)
        mainLayer->removeGeometry(ls.get());

    circlePointList.clear();
    lineStringList.clear();
}

void MapWindow::updateMap()
{
    mapControl->updateRequestNew();
}
